package com.lytfly.flowable.modules.flow.service;

import com.lytfly.flowable.domain.Query;
import com.lytfly.flowable.domain.task.*;
import com.lytfly.flowable.exception.FlowException;
import org.apache.ibatis.annotations.Param;
import org.flowable.idm.api.User;
import org.flowable.task.api.Task;

import java.util.List;

/**
 * @program: flow
 * @description: flowable的任务service
 * @author: Bruce.Liu
 * @create: 2021-04-20 14:16
 **/
public interface IFlowableTaskService {

    /**
     * 通过任务id获取任务对象
     *
     * @param taskId 任务id
     * @return
     */
    public Task findTaskById(String taskId);

    /**
     * 查询我的待办任务总数
     *
     * @param params
     * @return
     */
    Long getApplyingTaskCont(@Param("params") TaskQueryParamsVO params);


    /**
     * 查询我的待办任务列表
     *
     * @param taskQueryParamsVO 查询参数
     * @param query             分页
     * @return
     */
    List<TaskVO> getApplyingTaskListByPage(TaskQueryParamsVO taskQueryParamsVO, Query query);

    /**
     * 查询我的已办任务
     *
     * @param taskQueryParamsVO 查询参数
     * @param query             分页
     * @return
     */
    List<TaskVO> getAppliedTaskListByPage(TaskQueryParamsVO taskQueryParamsVO, Query query);

    /**
     * 执行任务
     *
     * @param completeTaskVO 执行任务VO
     * @throws FlowException
     */
    void complete(CompleteTaskVO completeTaskVO) throws FlowException;

    /**
     * 获取可驳回节点列表
     * 驳回：当前处理人可以驳回历史走过的任何一个节点
     * 1、驳回任意普通节点
     * 2、驳回多实例节点
     * 3、驳回并行网关节点
     * 4、驳回子流程节点
     * 5、子流程节点驳回主流程节点
     * <p>
     * 实际情况中，为了获取可驳回的节点列表，我们做了一些规定，比方说并行网关节点，要求必须成对出现，也只能驳回到并行网关节点的 fork节点
     * https://blog.csdn.net/liuwenjun05101/article/details/103482334?spm=1001.2014.3001.5501
     *
     * @param taskId            任务id
     * @param processInstanceId 流程实例id
     * @return
     */
    public List<FlowNodeVO> getBackNodeListByProcessInstanceId(String processInstanceId, String taskId);

    /**
     * 驳回任意节点 暂时没有考虑子流程
     *
     * @param backTaskVO 参数
     * @return
     */
    public void backToStepTask(BackVO backTaskVO);

    /**
     * 任务前加签 （如果多次加签只能显示第一次前加签的处理人来处理任务）
     * 多个加签人处理完毕任务之后又流到自己这里
     * 向前加签:任务在A这里，A这个时候需要BCD核对一下，等BCD核对之后又回到A这里
     * https://blog.csdn.net/liuwenjun05101/article/details/103442244?spm=1001.2014.3001.5501
     *
     * @param addSignTaskVO 参数
     * @return
     */
    public void beforeAddSignTask(SignVO addSignTaskVO);

    /**
     * 任务后加签（加签人自己自动审批完毕加签多个人处理任务）
     * 向后加签:任务在A这里，A这个时候需要BCD处理这个事情，处理完毕之后就不用管了，继续后面的审批环节
     * https://blog.csdn.net/liuwenjun05101/article/details/103442244?spm=1001.2014.3001.5501
     *
     * @param addSignTaskVO 参数
     * @return
     */
    public void afterAddSignTask(SignVO addSignTaskVO);

    /**
     * 任务加签
     *
     * @param addSignTaskVo 参数
     * @param typeFlag      true:向后加签;false:向前加签;
     * @return
     */
    public void addSignTask(SignVO addSignTaskVo, Boolean typeFlag);

    /**
     * 反签收任务
     * 反签收：就是把执行人设置为空
     * 注意事项：反签收的时候，一定要先确定是否有候选人或者候选组，如果没有的话，不能反签收。因为会导致这个任务无法认领。
     * https://blog.csdn.net/liuwenjun05101/article/details/103438645?spm=1001.2014.3001.5501
     *
     * @param claimTaskVO 参数
     * @return
     */
    public void unClaimTask(ClaimTaskVO claimTaskVO);

    /**
     * 签收任务
     * 签收：一般情况就是多个候选人，或者候选组的情况下，要先把这个任务签收下来，以免别人又做了同样的任务。
     * https://blog.csdn.net/liuwenjun05101/article/details/103438645?spm=1001.2014.3001.5501
     *
     * @param claimTaskVO 参数
     * @return
     */
    public void claimTask(ClaimTaskVO claimTaskVO);

    /**
     * 委派任务
     * 解释：委派
     * A由于某些原因不能处理该任务，可以把任务委派给用户B代理，当B处理完成之后再次回到用户A这里，在这个过程中A是任务的所有者，B是该任务的办理人
     * A->B->A
     * https://blog.csdn.net/liuwenjun05101/article/details/103430327?spm=1001.2014.3001.5501
     *
     * @param delegateTaskVO 参数
     * @return
     */
    public void delegateTask(DelegateTaskVO delegateTaskVO);

    /**
     * 转办
     * https://blog.csdn.net/liuwenjun05101/article/details/103420401?spm=1001.2014.3001.5501
     *
     * @param turnTaskVO 转办任务VO
     * @return 返回信息
     */
    public void turnTask(TurnTaskVO turnTaskVO);

    /**
     * 通过任务id判断当前节点是不是并行网关的节点
     *
     * @param taskId 任务id
     * @return
     */
    public boolean checkParallelGatewayNode(String taskId);

    /**
     * 通过流程实例id获取流程实例的待办任务审批人列表
     *
     * @param processInstanceId 流程实例id
     * @return
     */
    public List<User> getApproverList(String processInstanceId);


}
